import React, { useEffect, useRef, useState } from "react";
import {
  Modal,
  ModalContent,
  ModalHeader,
  ModalBody,
  ModalFooter,
  Button,
  useDisclosure,
  Input,
  Select,
  SelectItem,
  Textarea,
} from "@nextui-org/react";
import { showToast } from "../toast";
import { useGlobalState, useHttp } from "@/hooks";
import { App } from "@/entities/App";
import { useRouter } from "next/router";

type Props = {
  size?:
    | "xs"
    | "sm"
    | "md"
    | "lg"
    | "xl"
    | "2xl"
    | "3xl"
    | "4xl"
    | "5xl"
    | "full";
  openCallback?: Fn;
  closeCallback?: Fn;
  confirmCallback?: Fn;
  cancelBtnText?: string;
  confirmBtnText?: string;
  triggerBtnText?: string;
  mode: "create" | "edit";
  datasetId?: number;
  visible?: boolean;
};

const DatasetModal: React.FC<Props> = ({
  size = "3xl",
  openCallback,
  closeCallback,
  triggerBtnText,
  confirmCallback,
  cancelBtnText,
  confirmBtnText,
  mode,
  datasetId,
  visible,
}) => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  const [name, setName] = useState("");
  const [defValueId, setDefValueId] = useState<number | null>(0);
  const [value, setValue] = useState("[]");
  const [introduce, setIntroduce] = useState("");
  const [app, setApp] = useState("");
  const [appList, setAppList] = useState<
    Array<{ id: number; name: string; introduce: string }>
  >([]);

  const isCreateMode = mode === "create";

  const router = useRouter();
  const appid = Number(
    (router.query.appid as string) || (router.query.appId as string)
  );

  useEffect(() => {
    if (visible) {
      handleOpenRef.current();
    }
  }, [visible]);

  const resetInputs = () => {
    setName("");
    setDefValueId(null);
    setIntroduce("");
    setApp("");
    setValue("[]");
  };

  const getAppList = async (silent = false) => {
    const res = await http.get(
      "/api/app/simpleList",
      {},
      { isOpenLoading: true, silent }
    );
    if (res?.success) {
      setAppList(res.data as App[]);
    }
  };

  const getAppListRef = useRef(getAppList);

  const handleOpen = async () => {
    if (openCallback) {
      openCallback();
    }
    onOpen();

    // getAppListRef.current(true);

    isCreateMode && resetInputs();
    if (!isCreateMode && datasetId) {
      const res = await http.get(
        `/api/dataset/detail`,
        { datasetid: datasetId },
        { silent: true }
      );
      if (res?.success) {
        setName(res.data.name);
        setDefValueId(res.data.defValueId ?? null);
        setIntroduce(res.data.introduce);
        setApp(res.data.app);
        setValue(res.data.value);
      }
    }
  };

  const handleOpenRef = useRef(handleOpen);
  handleOpenRef.current = handleOpen;

  const handleClose = () => {
    if (closeCallback) {
      closeCallback();
    }
    onClose();
  };

  useEffect(() => {
    if (datasetId) {
      // get app info
    }
  }, [datasetId]);

  const { isLoading, http } = useHttp();
  // const { id } = useGlobalState('user', 'userInfo')

  const handleConfirm = async () => {
    if (!name) {
      showToast("Please enter dataset name");
      return;
    }

    if (!introduce) {
      showToast("Please enter dataset description");
      return;
    }

    // if (!app) {
    //   showToast("Please select app");
    //   return;
    // }

    if (!value) {
      showToast("Please enter dataset value");
      return;
    } else {
      try {
        const data = JSON.parse(value);
        if (defValueId) {
          // if specify defalt id, the dataset can be treated as an object
          // the shape of value should like [{id: 1, data: {foo: 'bar'} }, ...]
          const ok = data.every((item: any) => {
            return (
              Object.keys(item).length === 2 &&
              item.id !== undefined &&
              item.data !== undefined
            );
          });

          if (!ok) {
            showToast("Please enter valid Array<{id, data}> value");
            return;
          }
        }
      } catch (e) {
        console.log("🚀 ~ handleConfirm ~ e:", e);
        showToast("Please enter valid Array<Object> value");
        return;
      }
    }

    const res = await http.post(
      isCreateMode ? "/api/dataset/create" : "/api/dataset/update",
      {
        ...(!isCreateMode ? { datasetid: datasetId } : {}),
        name,
        value,
        introduce,
        appid,
        ...{ defValueId },
      }
    );

    if (res?.success) {
      handleClose();
    }

    if (confirmCallback) {
      confirmCallback(res?.success);
    }
  };

  return (
    <div className="create-dataset-modal">
      {isCreateMode && (
        <Button size="md" radius="md" color="primary" onClick={handleOpen}>
          {triggerBtnText || "Add"}
        </Button>
      )}
      <Modal size={size} isOpen={isOpen} onClose={handleClose}>
        <ModalContent>
          {(onClose) => (
            <>
              <ModalHeader className="flex flex-col gap-1">
                {isCreateMode ? "Create" : "Edit"} Dataset
              </ModalHeader>
              <ModalBody>
                <div className="flex flex-col gap-4">
                  <div className="control-line">
                    <Input
                      label="Name"
                      size="md"
                      labelPlacement="outside"
                      value={name}
                      onChange={(e) => setName(e.target.value)}
                      className="w-full"
                      isRequired
                      placeholder="Enter dataset name"
                    />
                  </div>
                  <div className="control-line">
                    <Textarea
                      labelPlacement="outside"
                      isRequired
                      label="Description"
                      placeholder="Enter dataset description"
                      className="w-full"
                      value={introduce}
                      onChange={(e) => setIntroduce(e.target.value)}
                    />
                  </div>
                  {/* <div className="control-line">
                    <Select
                      labelPlacement="outside"
                      isRequired
                      size="md"
                      selectedKeys={[app]}
                      onChange={(e) => setApp(e.target.value)}
                      className="w-full"
                      label="App"
                      placeholder="Select app"
                    >
                      {appList.map((app) => (
                        <SelectItem key={app.id} value={app.id}>
                          {app.name}
                        </SelectItem>
                      ))}
                    </Select>
                  </div> */}
                  <div className="control-line">
                    <Textarea
                      labelPlacement="outside"
                      isRequired
                      label="Value"
                      placeholder="Enter data list"
                      className="w-full"
                      value={value}
                      onChange={(e) => setValue(e.target.value)}
                    />
                  </div>

                  <div className="control-line">
                    <Input
                      label="Default Id"
                      placeholder="Default Id"
                      type="number"
                      isClearable
                      onClear={() => setDefValueId(null)}
                      size="md"
                      labelPlacement="outside"
                      value={defValueId ? defValueId + "" : ""}
                      onChange={(e) => setDefValueId(Number(e.target.value))}
                      className="w-full"
                    />
                    <p className="mt-4 text-sm text-gray-400">
                      if specify defalt id, the dataset can be treated as an
                      object, reading and writing operation use the default id
                    </p>
                  </div>
                </div>
              </ModalBody>
              <ModalFooter>
                <Button
                  isLoading={isLoading}
                  color="primary"
                  onPress={handleConfirm}
                >
                  {confirmBtnText ?? isCreateMode ? "Create" : "Save"}
                </Button>
                <Button color="primary" variant="flat" onPress={onClose}>
                  {cancelBtnText || "Cancel"}
                </Button>
              </ModalFooter>
            </>
          )}
        </ModalContent>
      </Modal>
    </div>
  );
};

export default DatasetModal;
